import { from, map, filter, Subscription, concatMap, of } from "rxjs";
import { OperatorManager } from "../../operators/operatorManager";
import { RunTime } from "../../runtime";
import { BaseController } from "../baseController";
import { EventClass } from "@lib/alen-helper/node/baseClass";
import { get_back_observable } from "@lib/alen-helper/node/fun";
import { Application } from "../../application/application";

export class WindowController extends BaseController<'window', {
    'show': { item: OperatorManager.Item<'window'> },
    'hide': { item: OperatorManager.Item<'window'> },
    'ready': { item: OperatorManager.Item<'window'> },
    'close': { item: OperatorManager.Item<'window'>, data: Runtime.OperatorCls.Window.Events['close'] },
}> {
    constructor(
        private _runTime: RunTime,
        BaseOptions?: Partial<EventClass.BaseOptions>,
    ) {
        super('WindowController', 'window', _runTime.operatorManager, BaseOptions);
        this._sub();
    }

    private _subs: Subscription | null = null;
    private _unSub() {
        if (this._subs) this._subs.unsubscribe();
        this._subs = null;
    }

    private _sub() {
        this._subs = this.event('build')
            .subscribe(data => {
                //data.item.operator.runTimeMsg
                const subs = this.event('destroy')
                    .pipe(filter(e => e.item.id === data.item.id))
                    .subscribe(() => {
                        subs.unsubscribe();
                    });
                subs.add(
                    data.item.operator.event('show')
                        .subscribe(e => {
                            this.triggerEvent('show', { item: data.item });
                        })
                );
                subs.add(
                    data.item.operator.event('hide')
                        .subscribe(e => {
                            this.triggerEvent('hide', { item: data.item });
                        })
                );
                subs.add(
                    data.item.operator.event('ready')
                        .subscribe(e => {
                            this.triggerEvent('ready', { item: data.item });
                        })
                );
                data.item.operator.addEventHandler('close', e => {
                    return this.triggerEventEnd('close', { item: data.item, data: e.data })
                        .pipe(map(data => {
                            e.data.preventClose = data.data.preventClose;
                        }))
                });
            });
    }

    send(appid: string, id: string, data: Omit<Application.Message, 'target'>) {
        const app = this._runTime.getApp(appid);
        if (!app) return of(false);
        return app.send('app_event_message', { target: { appid, id }, ...data });
    }

    show(appid: string, id: string) {
        const item = this.getOperator(appid, id);
        if (!item) return of(false);
        return get_back_observable(item.operator.show());
    }

    hide(appid: string, id: string) {
        const item = this.getOperator(appid, id);
        if (!item) return of(false);
        return get_back_observable(item.operator.hide());
    }

    close(appid: string, id: string) {
        const item = this.getOperator(appid, id);
        if (!item) return of(false);
        return get_back_observable(item.operator.close());
    }
}